package com.angel.architecture.interceptors;

import java.lang.reflect.Field;

import org.aopalliance.intercept.ConstructorInvocation;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import com.angel.architecture.annotations.services.GenericDAO;
import com.angel.architecture.exceptions.ApplicationException;
import com.angel.architecture.exceptions.NonBusinessException;
import com.angel.architecture.flex.locator.ObjectLocator;
import com.angel.common.helpers.ReflectionHelper;

/**
 *	TODO Write comments.
 *
 * @user William
 */
public class GenericServiceInterceptor implements MethodInterceptor {

	public Object construct(ConstructorInvocation constructorInvocation) throws Throwable {
        try {
        	System.out.println("*************************************************");
        	System.out.println("*************************************************");
        	//Object object = constructorInvocation.getThis();
        	
        	Object constructed = constructorInvocation.proceed();
        	Class<?> objectClass = constructed.getClass();
        	boolean isAnnotationPresent = objectClass.isAnnotationPresent(GenericDAO.class);
        	if(isAnnotationPresent){
        		GenericDAO genericDAO = objectClass.getAnnotation(GenericDAO.class);
        		boolean containsBean = ObjectLocator.contains(genericDAO.daoName());
        		if(containsBean){
        			Object dao = ObjectLocator.getBeanByName(genericDAO.daoName());
        			Field genericDAOField = ReflectionHelper.getFieldByName(objectClass, "genericDAO");
        			if(genericDAOField.get(constructed) == null){
        				genericDAOField.setAccessible(true);
        				ReflectionHelper.setFieldValue(constructed, genericDAOField, dao);
        				genericDAOField.setAccessible(false);
        			}
        		}
        	}
        	System.out.println("*************************************************");
        	System.out.println("*************************************************");
        	return constructed;
        } catch (Throwable throwable) {
            if (!(throwable instanceof ApplicationException)) {
                throw new NonBusinessException(throwable);
            }
            throw throwable;
        }		
	}

	public Object invoke(MethodInvocation methodInvocation) throws Throwable {
		try {
			System.out.println("*************************************************");
			System.out.println("*************************************************");
        	Object object = methodInvocation.getThis();
        	Class<?> objectClass = object.getClass();
        	Object constructed = methodInvocation.proceed();
        	boolean isAnnotationPresent = objectClass.isAnnotationPresent(GenericDAO.class);
        	if(isAnnotationPresent){
        		GenericDAO genericDAO = objectClass.getAnnotation(GenericDAO.class);
        		boolean containsBean = ObjectLocator.contains(genericDAO.daoName());
        		if(containsBean){
        			Object dao = ObjectLocator.getBeanByName(genericDAO.daoName());
        			Field genericDAOField = ReflectionHelper.getFieldByName(objectClass, "genericDAO");
        			if(genericDAOField.get(constructed) == null){
        				genericDAOField.setAccessible(true);
        				ReflectionHelper.setFieldValue(constructed, genericDAOField, dao);
        				genericDAOField.setAccessible(false);
        			}
        		}
        	}
        	System.out.println("AAAAAAAAAAAAA************************************");
        	System.out.println("*************************************************");
        	return constructed;
        } catch (Throwable throwable) {
            if (!(throwable instanceof ApplicationException)) {
                throw new NonBusinessException(throwable);
            }
            throw throwable;
        }
	}
}
